/**
 * OSAmI: Open Source Ambient Intelligence
 * Copyright (C) 2010 Bull S.A.S.
 * Contact: osami-general@osami-commons.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 */

package org.osami.gateway.jennic.internal.message.parser;

import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;

import org.apache.felix.ipojo.annotations.Component;
import org.apache.felix.ipojo.annotations.Provides;
import org.osami.gateway.jennic.IPayload;
import org.osami.gateway.jennic.IPayloadParser;
import org.osami.gateway.jennic.PayloadParsingException;
import org.osami.gateway.jennic.internal.message.ByePayload;
import org.osami.gateway.jennic.internal.message.EventPayload;
import org.osami.gateway.jennic.internal.message.HelloPayload;
import org.osami.gateway.jennic.internal.message.MetadataPayload;

/**
 * Created by IntelliJ IDEA.
 * User: guillaume
 * Date: 26 mai 2010
 * Time: 18:24:41
 * To change this template use File | Settings | File Templates.
 */
@Component
@Provides
public class DefaultPayloadParser implements IPayloadParser {

    public IPayload parse(String message) throws PayloadParsingException {
        if (message != null) {
            if (message.startsWith(Constants.DEVICE_HELLO_PREFIX)) {
                String remaining = message.substring(Constants.DEVICE_HELLO_PREFIX.length());
                String[] fragments = splitMessage(remaining);
                return new HelloPayload(fragments[0], fragments[1], Integer.parseInt(fragments[2]));
            }
            else if (message.startsWith(Constants.DEVICE_BYE_PREFIX)) {
                String remaining = message.substring(Constants.DEVICE_BYE_PREFIX.length());
                String[] fragments = splitMessage(remaining);
                return new ByePayload(fragments[0], fragments[1], Integer.parseInt(fragments[2]));
            }
            else if (message.startsWith(Constants.DEVICE_PROBE_PREFIX)) {
                // Do nothing.
            }
            else if (message.startsWith(Constants.DEVICE_GETMETADATA_PREFIX)) {
                // Do nothing.
            }
            else if (message.startsWith(Constants.DEVICE_METADATA_PREFIX)) {
                String remaining = message.substring(Constants.DEVICE_METADATA_PREFIX.length());
                return parseMetadataPayload(remaining);
            }
            else if (message.startsWith(Constants.DEVICE_EVENT_PREFIX)) {
                String remaining = message.substring(Constants.DEVICE_EVENT_PREFIX.length());
                return parseEventPayload(remaining);
            }
        }

        // Not a discovery / eventing message.
        throw new PayloadParsingException("Not a discovery message");
    }

    private IPayload parseEventPayload(String payload) throws PayloadParsingException {
        String id;
        String [] strings;

        strings = payload.split(Constants.DEVICE_FIELD_SEPARATOR);

        if (strings.length >= 2) {
            id = strings[0];

            Logger.getLogger(DefaultPayloadParser.class.getName()).finer("Received \u001B[1;31mEVENT\u001B[m message from device with id \"" + id + "\" !");


            payload = strings[1];

            // ID
            strings = payload.split(Constants.DEVICE_EVENT_FIELD_SEPARATOR);

            // Key=Value pairs
            Map<String, String> dict = new HashMap<String, String>();
            for (int i = 0; i < strings.length; i++) {
                String[] parts = strings[i].split("\\" + Constants.DEVICE_EVENT_KV_SEPARATOR);

                if ((parts.length != 2) || (strings[i].equals(""))) {
                    throw new PayloadParsingException("Malformed Event message");
                } else {
                    dict.put(parts[0], parts[1]);
                }
            }

            return new EventPayload(id, dict);

        }
        throw new PayloadParsingException("Malformed Event message");
    }

    private IPayload parseMetadataPayload(String payload) throws PayloadParsingException {
        String id;
        String [] strings;

        strings = payload.split(Constants.DEVICE_FIELD_SEPARATOR);

        if (strings.length >= 2) {
            id = strings[0];

            Logger.getLogger(DefaultPayloadParser.class.getName()).finer("Received \u001B[1;31mMETADATA\u001B[m message from device with id \"" + id + "\" !");


            payload = strings[1];

            // ID
            strings = payload.split(Constants.DEVICE_METADATA_FIELD_SEPARATOR);

            // Key=Value pairs
            Map<String, String> dict = new HashMap<String, String>();
            for (int i = 0; i < strings.length; i++) {
                String[] parts = strings[i].split("\\" + Constants.DEVICE_METADATA_KV_SEPARATOR);

                if ((parts.length != 2) || (strings[i].equals(""))) {
                    throw new PayloadParsingException("Malformed Event message");
                } else {
                    dict.put(parts[0], parts[1]);
                }
            }

            return new MetadataPayload(id, dict);

        }
        throw new PayloadParsingException("Malformed Event message");
    }

    private String[] splitMessage(String remaining) {
        return remaining.split(Constants.DEVICE_FIELD_SEPARATOR);
    }
}
